package com.aaa.service.impl;


import com.aaa.mapper.WorkAttendanceMapper;
import com.aaa.entity.WorkAttendance;
import com.aaa.entity.WorkAttendanceConfig;
import com.aaa.service.WorkAttendanceService;
import com.aaa.util.LocationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class WorkAttendanceServiceImpl implements WorkAttendanceService {

    @Autowired
    private WorkAttendanceMapper workAttendanceMapper;

    // 初始化日志记录器，用于记录异常信息，方便后续排查问题
    private static final Logger logger = LoggerFactory.getLogger(WorkAttendanceServiceImpl.class);

    // 工作类型常量定义
    private static final String WORK_TYPE_OFFICE = "社内";
    private static final String WORK_TYPE_OUTSIDE = "社外";

    // 打卡类型常量定义
    private static final String CHECK_TYPE_WORK_START = "上班";
    private static final String CHECK_TYPE_WORK_END = "下班";

    @Autowired
    private WorkAttendanceConfig workAttendanceConfig;

    @Override
    @Transactional
    public Map<String, Object> checkIn(Long userId, String userName, WorkAttendance workAttendance) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", false);//默认值
        result.put("message", "打卡失败");
        result.put("data", null);

        // 1. 验证参数
        if (userId == null || !StringUtils.hasText(userName) || workAttendance == null || !StringUtils.hasText(workAttendance.getCheckType()) || !StringUtils.hasText(workAttendance.getWorkType())) {
            logger.warn("打卡参数不完整, userId: {}, userName: {}, workAttendance: {}", userId, userName, workAttendance);
            result.put("message", "参数不完整");
            return result;
        }
        // 4. 获取今日打卡记录
        List<WorkAttendance> todayRecords = workAttendanceMapper.getTodayRecords(userId);
        logger.debug("获取用户今日打卡记录, userId: {}, 记录数: {}", userId, todayRecords.size());

        // 5. 检查今日是否已有其他类型的打卡
        boolean hasOfficeRecord = false;//社内打卡记录
        boolean hasOutsideRecord = false;//社外打卡记录

        for (WorkAttendance record : todayRecords) {
            if (WORK_TYPE_OFFICE.equals(record.getWorkType())) {
                hasOfficeRecord = true;
            } else if (WORK_TYPE_OUTSIDE.equals(record.getWorkType())) {
                hasOutsideRecord = true;
            }
        }

        // 6. 检查是否已经进行了社内或社外打卡
        if (WORK_TYPE_OFFICE.equals(workAttendance.getWorkType()) && hasOutsideRecord) {
            logger.warn("用户今日已进行社外打卡，不能进行社内打卡, userId: {}", userId);
            result.put("message", "今日已进行社外打卡，不能进行社内打卡");
            return result;
        }
        if (WORK_TYPE_OUTSIDE.equals(workAttendance.getWorkType()) && hasOfficeRecord) {
            logger.warn("用户今日已进行社内打卡，不能进行社外打卡, userId: {}", userId);
            result.put("message", "今日已进行社内打卡，不能进行社外打卡");
            return result;
        }

        // 7. 检查打卡顺序和重复打卡
        boolean hasWorkStartRecord = false;//上班
        boolean hasWorkEndRecord = false;//下班

        for (WorkAttendance record : todayRecords) {
            if (CHECK_TYPE_WORK_START.equals(record.getCheckType())) {
                hasWorkStartRecord = true;
            } else if (CHECK_TYPE_WORK_END.equals(record.getCheckType())) {
                hasWorkEndRecord = true;
            }
        }

        // 验证下班打卡前必须有上班打卡
        if (CHECK_TYPE_WORK_END.equals(workAttendance.getCheckType()) && !hasWorkStartRecord) {
            logger.warn("用户尝试进行下班打卡但未进行上班打卡, userId: {}", userId);
            result.put("message", "请先进行上班打卡");
            return result;
        }

        // 验证是否重复打卡
        if (CHECK_TYPE_WORK_START.equals(workAttendance.getCheckType()) && hasWorkStartRecord) {
            logger.warn("用户今日已完成上班打卡，尝试重复操作, userId: {}", userId);
            result.put("message", "今日已完成上班打卡，请勿重复操作");
            return result;
        }
        if (CHECK_TYPE_WORK_END.equals(workAttendance.getCheckType()) && hasWorkEndRecord) {
            logger.warn("用户今日已完成下班打卡，尝试重复操作, userId: {}", userId);
            result.put("message", "今日已完成下班打卡，请勿重复操作");
            return result;
        }

        // 8. 社外打卡必填信息验证
        if (WORK_TYPE_OUTSIDE.equals(workAttendance.getWorkType())) {
            if (!StringUtils.hasText(workAttendance.getCompanyName())) {
                logger.warn("用户社外打卡未填写公司名称, userId: {}", userId);
                result.put("message", "社外打卡需填写公司名称");
                return result;
            }
        }

        // 9. 社内打卡需要验证位置
        if (WORK_TYPE_OFFICE.equals(workAttendance.getWorkType())) {
            if (!validateLocation(workAttendance.getLatitude(), workAttendance.getLongitude())) {
                logger.warn("用户不在打卡范围内, userId: {}, 位置: [{}, {}]", userId, workAttendance.getLatitude(), workAttendance.getLongitude());
                result.put("message", "不在打卡范围内");
                return result;
            }
        }
        try {
            // 10. 创建打卡记录
            WorkAttendance attendance = new WorkAttendance();
            attendance.setUserId(userId);
            attendance.setUserName(userName);
            attendance.setCheckType(workAttendance.getCheckType());
            attendance.setWorkType(workAttendance.getWorkType());
            attendance.setLatitude(workAttendance.getLatitude());
            attendance.setLongitude(workAttendance.getLongitude());
            attendance.setLocation(workAttendance.getLocation());
            attendance.setCheckTime(LocalDateTime.now());
            attendance.setCompanyName(workAttendance.getCompanyName());
            attendance.setBusinessType(workAttendance.getBusinessType());
            attendance.setBusinessDescription(workAttendance.getBusinessDescription());
            attendance.setIsWorkStartChecked(CHECK_TYPE_WORK_START.equals(workAttendance.getCheckType()));
            attendance.setIsWorkEndChecked(CHECK_TYPE_WORK_END.equals(workAttendance.getCheckType()));
            attendance.setStatus(1);
            attendance.setCreateTime(LocalDateTime.now());
            attendance.setUpdateTime(LocalDateTime.now());

            // 11. 保存打卡记录
            workAttendanceMapper.insert(attendance);

            // 打卡成功
            logger.info("用户打卡成功, userId: {}, userName: {}, 打卡类型: {}, 工作类型: {}, 位置: [{}, {}]",
                    userId, userName, workAttendance.getCheckType(), workAttendance.getWorkType(),
                    workAttendance.getLatitude(), workAttendance.getLongitude());

            result.put("success", true);
            result.put("message", "打卡成功");
            result.put("data", attendance);
        } catch (Exception e) {
            // 捕获保存记录过程中的异常
            logger.error("保存打卡记录异常, userId: {}, 原因: {}", userId, e.getMessage(), e);
            result.put("message", "系统错误，请稍后再试");
        }

        return result;
    }

    @Override
    public boolean validateLocation(Double latitude, Double longitude) {
        if (latitude == null || longitude == null) {
            logger.warn("打卡位置坐标为空, latitude: {}, longitude: {}", latitude, longitude);
            return false;
        }
        //使用注入的配置属性,社内打卡才需要验证距离
        double distance =LocationUtils.calculateDistance(
                latitude, longitude,
                workAttendanceConfig.getCompanyLatitude(), workAttendanceConfig.getCompanyLongitude()
        );
        boolean isInRange = distance <= workAttendanceConfig.getInternalCheckRange();
        if (!isInRange) {
            logger.warn("用户不在打卡范围内, 距离公司: {}米, 允许范围: {}米",
                    distance, workAttendanceConfig.getInternalCheckRange());
        }
        return isInRange;
    }
}
